﻿/*
 * systool.cpp
 *
 *  Created on: 2018年2月16日
 *      Author: work
 */

#include <iostream>
#include <dm/os/sys/process.hpp>
#include <dm/os/sys/task_mgr.hpp>
#include <dm/os/sys/task.hpp>
#include <dm/os/sys/host_mgr.hpp>
#include <dm/os/sys/host.hpp>

#include <boost/program_options.hpp>

using namespace std;
using namespace boost::program_options;
using namespace dm::os::sys;

void printHost( CHost& host ){
	if( !host.refresh() ){
		cout <<"获取主机信息失败:"<<host.getPos().getBufferIndex()<<"."<<host.getPos().getBufferOffset()<<endl;
	}else{
		dm::CIp4::ip_str_t net1;
		dm::CIp4::ip_str_t net2;

		host.getInfo().net1_ip.getStr(net1);
		host.getInfo().net2_ip.getStr(net2);

		cout <<host.getInfo().id<<'\t'
				<<host.getInfo().name<<'\t'
				<<host.getInfo().desc<<'\t'
//				<<dm::os::sys::SHostState::state2str(host.getState().state)<<'\t'
//				<<net1<<'('<<dm::os::sys::SHostState::netState2str(host.getState().net1State)<<")\t"
//				<<net2<<'('<<dm::os::sys::SHostState::netState2str(host.getState().net2State)<<")\t"
				<<host.getInfo().backed<<'\t'
				<<dm::CDateTime(host.getTimeStamp()).toString()<<'\t'
				<<host.getRunTimeStamp().secs()<<'.'<<host.getRunTimeStamp().nsecs()<<endl;
	}
}

int main( int argc,char* argv[] ){
	options_description desc("【DM2016帮助文档】\n DM系统工具。\n\t基于DM2016系统构建\n支持以下选项");

	options_description opts_generic("一般选项");
	opts_generic.add_options()
			("help,h","显示本帮助信息")
			("version,v","显示版本及编译信息")
			;
	desc.add(opts_generic);

	options_description opts_cmd("命令");
	opts_cmd.add_options()
			("info,i","显示系统状态")
			("stop",value<int>(),"停止任务")
			("exit,x","系统退出")
			("reset","复位系统")
			("init","初始化数据库表")
			;

	desc.add(opts_cmd);

	options_description opts_host("主机命令");
	opts_host.add_options()
			("id",value<int>(),"指定主机ID号")
			("name",value<string>(),"指定主机名称")
			("state",value<int>(),"设置主机状态")
			("net1-state",value<int>(),"设置主机网络1状态")
			("net2-state",value<int>(),"设置主机网络2状态")
			("host-cmd",value<string>(),"主机命令:help查看帮助")
			;
	desc.add(opts_host);

	variables_map vm;
	try{
		store(parse_command_line(argc,argv,desc),vm);
		notify(vm);
	}catch( std::exception& ex ){
		cout << ex.what()<<endl;
		return 1;
	}

	if( vm.count("version") ){
		cout <<"V1.0 构建于 "<<__DATE__<<endl;
		return 1;
	}

	if( vm.count("help") ){
		cout <<desc<<endl;
		return 1;
	}

	if( vm.count("init") ){
		cout <<"初始化数据库表..."<<flush;
//		if( dm::os::sys::CTaskMgr::CLoader().createTable() )
//			cout <<"成功"<<endl;
//		else
//			cout <<"失败"<<endl;
		return 0;
	}

	dm::os::sys::CTaskMgr& mgr = dm::os::sys::CTaskMgr::ins();

	if( vm.count("reset") ){
		cout <<"复位实时数据..."<<flush;
		mgr.reset();
		cout <<"完成"<<endl;
		return 0;
	}

	if( vm.count("info") ){
		dm::uint32 count = mgr.count();
		cout <<"系统任务数:"<<count<<endl;

		cout <<"序号| ID号 | 命 令 | 参 数 | 描 述 | 启动方式 | 延时启动 | 状态 | 进程号 | 开始执行时刻 | 最近刷新时刻 |  启  动  时  刻  | 下次执行时刻 | 最后检测时刻  " <<endl;
		for( int i=0;i<count;++i ){
//			dm::TScopedPtr<dm::os::sys::CTask> task(mgr.get(i));
//			if( !task )
//				cout <<"任务"<<i<<" 指针为空"<<endl;
//			else{
//				cout << i+1 <<" | "
//						<< task->getInfo().id<<" | "
//						<< task->getInfo().program.c_str() << " | "
//						<< task->getInfo().cmdline.c_str() << " | "
//						<< task->getInfo().desc.c_str()  <<" | "
//						<< task->getInfo().startModeString(task->getInfo().startMode) <<" | "
//						<<endl;
//			}
		}
	}

	if( vm.count("host-cmd") ){
		dm::os::sys::CHostMgr& hostMgr = dm::os::sys::CHostMgr::ins();

		string cmd = vm["host-cmd"].as<string>();
		if( cmd=="help" ){
			cout <<"主机命令支持:\n"
					<<"\tshow\t 显示主机信息。可以指定主机id或者主机名\n"
					<<"\tnews\t 加载新主机信息\n"
					<<"\treload\t 重新加载主机。需要指定id或者主机名\n"
					<<"\tunload\t 手动卸载主机信息。需要指定主机id或者主机名"
					<<"\tupdate\t 更新主机信息。需要指定主机id或者主机名，可以更新主机状态和网络状态"
					<<"\treset\t 服务主机管理"<<endl;
			cout <<"\n主机状态值对应关系如下:\n\t";
//			for( int i=0;i<=SHostState::SShutDown;++i )
//				cout <<i<<": "<<SHostState::state2str(SHostState::EState(i))<<',';
//
//			cout <<"\n主机网络状态值对应关系如下:\n\t";
//			for( int i=0;i<=SHostState::NsOffLine;++i )
//				cout <<i<<": "<<SHostState::netState2str(SHostState::ENetState(i))<<',';
//			cout <<endl;
			return 0;
		}else if( cmd=="show" ){
			int count = hostMgr.count();
			cout <<"主机数:"<<count<<endl;

			cout <<"ID号 |\t 主机名 |\t 描述 |\t 状态 |\t IP1 |\t IP2 |\t 备机ID |\t 时标 |\t 计时器"<<endl;
			if( vm.count("id") ){
				CHostMgr::pos_t pos = hostMgr.getPos(vm["id"].as<int>());
				CHost host(pos);
				if( !pos.isValid() )
					cout <<"未找到主机(ID:"<<vm["id"].as<int>()<<')'<<endl;
				else
					printHost(host);
			}else if( vm.count("name") ){
				CHostMgr::pos_t pos = hostMgr.getPos(vm["name"].as<string>().c_str());
				CHost host(pos);
				if( !pos.isValid() )
					cout <<"未找到主机(主机名:"<<vm["name"].as<string>()<<')'<<endl;
				else
					printHost(host);
			}else{
				dm::os::sys::CHostMgr::pos_t pos = hostMgr.firstPos();
				while( pos.isValid() ){
					dm::os::sys::CHost host(pos);
					printHost(host);
					pos = hostMgr.next(pos);
				}
			}
		}else if( cmd=="news" ){
			int count = hostMgr.count();
			cout <<"主机数:"<<count<<endl;
			cout <<"加载新的主机...";
			cout.flush();
			if( hostMgr.loadNews() )
				cout <<"成功!"<<endl;
			else
				cout <<"失败!"<<endl;

			cout <<"加载后主机数:"<<hostMgr.count()<<endl;
		}else if( cmd=="reload" ){
			if( vm.count("id") ){
				int id = vm["id"].as<int>();
				cout <<"重新加载主机(ID:"<<id<<")...";
				cout.flush();
				if( hostMgr.reload(id) )
					cout <<"成功"<<endl;
				else
					cout <<"失败"<<endl;
			}else if( vm.count("name") ){
				string name = vm["name"].as<string>();
				cout <<"重新加载主机(名字:"<<name<<")...";
				cout.flush();
				if( hostMgr.reload(name.c_str()) )
					cout <<"成功"<<endl;
				else
					cout <<"失败"<<endl;
			}else{
				cout <<"请指定主机ID或者主机名"<<endl;
			}

		}else if( cmd=="unload" ){
			if( vm.count("id") ){
				int id = vm["id"].as<int>();
				cout <<"卸载主机(ID:"<<id<<")...";
				cout.flush();
				if( hostMgr.unload(id) )
					cout <<"成功"<<endl;
				else
					cout <<"失败"<<endl;
			}else if(vm.count("name")){
				string name = vm["name"].as<string>();
				cout <<"卸载主机(名字:"<<name<<")...";
				cout.flush();
				if( hostMgr.unload(name.c_str()) )
					cout <<"成功"<<endl;
				else
					cout <<"失败"<<endl;
			}else{
				cout <<"请指定主机ID或者主机名"<<endl;
			}
		}else if( cmd=="update" ){
			CHost host;
			if( vm.count("id") ){
				int id = vm["id"].as<int>();
				CHostMgr::pos_t pos = hostMgr.getPos(id);
				if( !pos.isValid() ){
					cout <<"查找主机(ID:"<<id<<")失败"<<endl;
					return 1;
				}
				host.setPos(pos);
			}else if( vm.count("name") ){
				string name = vm["name"].as<string>();
				CHostMgr::pos_t pos = hostMgr.getPos(name.c_str());
				if( !pos.isValid() ){
					cout <<"查找主机(名字:"<<name<<")失败"<<endl;
					return 1;
				}
				host.setPos(pos);
			}else{
				cout <<"请指定主机ID或者主机名"<<endl;
			}

			if( !host.refresh() ){
				cout <<"获取主机信息失败"<<endl;
				return 1;
			}

			SHostState::EState state = SHostState::EState(-1);
			if( vm.count("state") ){
				state = SHostState::EState(vm["state"].as<int>());
				if( state<0 || state>SHostState::SShutDown ){
					cout <<"状态值无效:"<<int(state)<<endl;
					return 1;
				}
			}

			SHostState::ENetState net1State = SHostState::ENetState(-1);
			if( vm.count("net1-state") ){
				net1State = SHostState::ENetState(vm["net1-state"].as<int>());
				if( net1State<0 || net1State>SHostState::NsOffLine ){
					cout <<"网络1状态值无效:"<<int(net1State)<<endl;
					return 1;
				}
			}

			SHostState::ENetState net2State = SHostState::ENetState(-1);
			if( vm.count("net2-state") ){
				net2State = SHostState::ENetState(vm["net2-state"].as<int>());
				if( net2State<0 || net2State>SHostState::NsOffLine ){
					cout <<"网络2状态值无效:"<<int(net2State)<<endl;
					return 1;
				}
			}

			if( state==SHostState::EState(-1) && net1State==SHostState::ENetState(-1) && net2State==SHostState::ENetState(-1) ){
				cout <<"请设置需要更新的状态参数:state,net1-state或者net2-state"<<endl;
				return 1;
			}

			cout <<"更新主机状态: ID:"<<host.getInfo().id<<" 主机名:"<<host.getInfo().name<<" 描述:"<<host.getInfo().desc;
			if( host.updateState(state==SHostState::EState(-1)?nullptr:&state, net1State==SHostState::ENetState(-1)?nullptr:&net1State, net2State==SHostState::ENetState(-1)?nullptr:&net2State) )
				cout <<" 成功"<<endl;
			else
				cout <<" 失败"<<endl;

		}else if( cmd=="reset" ){
			cout <<"确定要复位主机管理模块(y/N):";
			cout.flush();
			char c;
			cin >> c;
			if( c=='y' || c=='Y' ){
				cout <<"主机管理模块复位中...";
				cout.flush();
				hostMgr.reset();
				cout <<"完成!"<<endl;
			}
		}
	}

	return 0;
}


